using System;
using System.Collections.Generic;

namespace FireStarter.Base
{
    //NOTE: the policy here has been that you don't add a setter unless
    //  really need it, because it creates dual ways to set a value, which opens
    //  the door to errors or desynchronisation.
    //  ie. rather than setting IModelProperty.Parent, set DMProperty.Class

    public interface IModelElement
    {
        IModelElement Parent { get; set; }
    }

    public interface IModelSolution : IModelElement
    {
        /// <summary>
        /// Gets all the model classes available to the solution, amalgamated
        /// from all the assemblies
        /// </summary>
        IList<IModelClass> ModelClasses { get; }

        string BOProjectName { get; set; }
        string LogicProjectName { get; set; }
        string BOTestProjectName { get; set; }
        string UIProjectName { get; set; }
        string UIVWGProjectName { get; set; }
        string UIWinProjectName { get; set; }
        IList<IModelAssembly> ModelAssemblies { get; }

        // Can't use SolutionName in templates because name comes from GenerationSettings and might
        // be different to DMSolution.SolutionName
        string ApplicationName { get; set; }
    }

    public interface IModelAssembly : IModelElement
    {
        string AssemblyName { get; set; }

        /// <summary>
        /// Gets all the model classes assigned to this assembly
        /// </summary>
        IList<IModelClass> ModelClasses { get; }
    }

    public interface IModelClass : IModelElement
    {
        string ClassName { get; set; }
        string DisplayName { get; set; }

        /// <summary>
        /// Gets the properties in this class only, excluding inherited ones
        /// </summary>
        IList<IModelProperty> Properties { get; }

        /// <summary>
        /// Gets all the properties in this class and inherited from parents
        /// </summary>
        IList<IModelProperty> AllProperties { get; }

        /// <summary>
        /// Gets the relationships owned by this class only, excluding inherited ones
        /// </summary>
        IList<IModelRelationship> Relationships { get; }

        /// <summary>
        /// Gets the relationships owned by this class and inherited from parents
        /// </summary>
        IList<IModelRelationship> AllRelationships { get; }

        string AssemblyName { get; }
        IModelClass SuperClass { get; }
        string SuperClassName { get; }
        string SuperClassAssemblyName { get; }
        string SuperClassChildID { get; }
        string SuperClassDiscriminator { get; }
        string InheritanceType { get; }
        string TableName { get; }
        IList<IModelProperty> PrimaryKeyProperties { get; }
        bool PrimaryKeyIsID { get; }
        IList<IModelKey> AlternateKeys { get; }
        bool HasSuperClass { get; }
        bool SuperClassDefIDIsEmpty { get; }
        bool SuperClassDefIDIsNotNullOrEmpty { get; }
        bool SuperClassDefIDIsNull { get; }
        bool HasPrimaryKeyWithProps { get; }
        bool NeedsRegeneration { get; set; }
        bool GenerateCode { get; }
    }

    public interface IModelProperty : IModelElement
    {
        string PropertyName { get; set; }
        IModelPropertyType PropertyType { get; }
        string PropertyTypeString { get; }
        bool HasSetter { get; set; }
        string DefaultValue { get; }
        bool IsCompulsory { get; }
        string Max { get; }
        string Min { get; }
        ModelLookupType LookupListType { get; }
        string DisplayName { get; }
        string ReadWriteRule { get; }
        string DatabaseField { get; }
        string Description { get; }
        bool AutoIncrementing { get; }
        bool HasLength { get; }
        int Length { get; }
        bool KeepValuePrivate { get; }
        bool GenerateCode { get; }
    }

    public interface IModelPropertyType : IModelElement
    {
        string PropertyTypeName { get; set; }
        string AssemblyName { get; set; }
        bool IsValueType { get; }
    }

    public interface IModelKey : IModelElement
    {
        string KeyName { get; }
        IList<IModelProperty> KeyProperties { get; }
    }

    public interface IModelRelationship : IModelElement
    {
        string RelationshipName { get; set; }
        string RelatedClass { get; }
        string RelatedAssembly { get; }
        bool IsMultiple { get; }
        IModelProperty Property { get; }
        IModelProperty RelatedProperty { get; }
        string RelatedPropertyName { get; } //TODO, get rid of this when we support .'s in the templates
        string PropertyName { get; } // and this.
        //DeleteParentAction DeleteParentAction { get; }
        string DeleteParentAction { get; }
        bool GenerateCode { get; }
    }

    public interface IModelDatabaseSettings : IModelElement
    {
        string Vendor{ get; set; }
        string Server { get; set; }
        string Port { get; set; }
        string Database { get; set; }
        string UserName { get; set; }
        string Password { get; set; }
    }


    public enum ModelLookupType
    {
        None,
        Simple,
        BusinessObject,
        Database
    }
}